package com.wonders.hisdoctor.station.project.record.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wonders.his.common.exception.CustomException;
import com.wonders.his.common.service.utils.CountAgeUtil;
import com.wonders.his.common.utils.DateUtils;
import com.wonders.his.common.utils.StringUtils;
import com.wonders.his.framework.dto.LoginUserDTO;
import com.wonders.his.framework.service.RedisCacheService;
import com.wonders.his.framework.service.TokenService;
import com.wonders.his.framework.utils.oracle.IdUtils;
import com.wonders.hisdoctor.station.constant.ServiceConstant;
import com.wonders.hisdoctor.station.enums.EffectiveEnum;
import com.wonders.hisdoctor.station.enums.OracleSequenceEnum;
import com.wonders.hisdoctor.station.project.base.domain.*;
import com.wonders.hisdoctor.station.project.base.mapper.*;
import com.wonders.hisdoctor.station.project.base.service.*;
import com.wonders.hisdoctor.station.project.record.bo.ModelDataBo;
import com.wonders.hisdoctor.station.project.record.mapper.RecordUseMapper;
import com.wonders.hisdoctor.station.project.record.service.IWdEditorService;
import com.wonders.hisdoctor.station.project.record.vo.*;
import com.wonders.hisdoctor.station.util.CommonUtil;
import com.wonders.hisdoctor.station.util.WdEditorHtmlUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;
import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * Description: 病例模板接口实现类
 *
 * @author tong-aj
 * <p>
 * Create: 2021-02-23 20:43
 */
@Service
public class WdEditorServiceImpl implements IWdEditorService {

    private WdeditorDsMapper wdeditorDsMapper;
    private IdUtils idUtils;
    private WdeditorDssetMapper wdeditorDssetMapper;
    private WdeditorDssetStaticMapper wdeditorDssetStaticMapper;
    private WdeditorDssetLoadMapper wdeditorDssetLoadMapper;
    private WdeditorDssetStorgeMapper wdeditorDssetStorgeMapper;
    private WdeditorDssetPropertyMapper wdeditorDssetPropertyMapper;
    private RecordUseMapper recordUseMapper;
    private IWdeditorDssetCustomService wdeditorDssetCustomService;
    private WebApplicationContext applicationContext;
    private WdeditorDssetCustomMapper wdeditorDssetCustomMapper;
    private WdeditorHistoryMapper wdeditorHistoryMapper;
    private IWdeditorHistoryService wdeditorHistoryService;
    private TokenService tokenService;
    private HospitalDictMapper hospitalDictMapper;
    private RedisCacheService redisCache;
    private IWdeditorDssetService wdeditorDssetService;
    private IWdeditorDssetLoadService wdeditorDssetLoadService;
    private IWdeditorDssetStaticService wdeditorDssetStaticService;
    private IWdeditorDssetStorgeService wdeditorDssetStorgeService;
    private IWdeditorDssetPropertyService wdeditorDssetPropertyService;
    private WdeditorPritemplatemasterMapper wdeditorPritemplatemasterMapper;
    private WdeditorPritemplatedetailMapper wdeditorPritemplatedetailMapper;
    private IWdeditorPritemplatedetailService wdeditorPritemplatedetailService;
    private PatMasterIndexMapper patMasterIndexMapper;
    private CommonUtil commonUtil;


    /**
     * Description: 查询所有病例模板数据源表
     * Param: []
     * return: java.util.List<com.wonders.hisdoctor.station.project.base.domain.WdeditorDs>
     * Author: tong-aj
     * Date: 2021/2/23
     */
    @Override
    public List<WdeditorDs> getWDEditorDSList() {
        return wdeditorDsMapper.selectList(new QueryWrapper<>());
    }

    /**
     * Description: 根据表名字段名，查所该字段所有值
     * Param: [tableName, columnName]
     * return: java.lang.String
     * Author: tong-aj
     * Date: 2021/2/22
     */
    @Override
    public List<String> getTableColumns(WdeditorDs wdeditorDs) {
        // 表名
        String tableName = wdeditorDs.getTableName();
        // 表类型
        Long tableType = wdeditorDs.getTableType();
        // 是否同数据库
        Long owndb = wdeditorDs.getOwndb();
        // 表示同数据库
        if (owndb.intValue() == 1 && tableType.intValue() != 3) {
            // 表示查询的是表的字段
            return recordUseMapper.getTableColumns(tableName);
        }
        return new ArrayList<>();
    }

    /**
     * Description: 根据表名字段名，查所该字段所有值
     * Param: [tableName, codeColumn, valueColumn]
     * return: java.util.List<java.lang.String>
     * Author: tong-aj
     * Date: 2021/2/25
     */
    @Override
    public List<String> getColumnValues(String tableName, String codeColumn, String valueColumn) {
        return recordUseMapper.getColumnValues(tableName, codeColumn, valueColumn);
    }

    /**
     * Description: 保存接口列表
     * Param: []
     * return: java.util.List<java.lang.String>
     * Author: tong-aj
     * Date: 2021/2/24
     */
    @Override
    public List<String> getSaveInterface() {
        // 一期默认返回
        List<String> result = new ArrayList<>();
        result.add("/record/saveRecord");
        return result;
    }

    /**
     * Description: 保存接口参数列表
     * Param: [interfaceName]
     * return: java.util.List<java.lang.String>
     * Author: tong-aj
     * Date: 2021/2/24
     */
    @Override
    public List<String> getInterfaceParams(String interfaceName) {
        // 定义返回集合
        List<String> result = new ArrayList<>();
        // 通过接口名称获取接口类、方法等信息
        Map<String, Object> methodInfo = getMethodInfo(interfaceName);
        // 获取接口方法
        Method method = (Method) methodInfo.get("method");
        // 获取保存方法的入参
        Parameter[] parameters = method.getParameters();
        List<Parameter> parameterList = Arrays.asList(parameters);
        if (!CollectionUtils.isEmpty(parameterList)) {
            parameterList.forEach(param -> {
                // 找到入参的类类型
                Class<?> type = param.getType();
                // 获取类中的所有字段
                Field[] declaredFields = type.getDeclaredFields();
                List<Field> fields = Arrays.asList(declaredFields);
                if (!CollectionUtils.isEmpty(fields)) {
                    // 放入返回结果集中
                    fields.forEach(field -> result.add(field.getName()));
                }
            });
        }

        return result;
    }

    /**
     * Description: 获取所有RequestMapping，通过保存接口找到对应的方法信息
     * Param: [interfaceName]
     * return: java.util.Map<java.lang.String,java.lang.String>
     * Author: tong-aj
     * Date: 2021/2/24
     */
    public Map<String, Object> getMethodInfo(String interfaceName) {
        // 获取springmvc处理器映射器组件对象 RequestMappingHandlerMapping无法直接注入
        RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class);
        // 获取url与类和方法的对应信息
        Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();
        // 定义返回结果
        Map<String, Object> result = new HashMap<>();
        a:
        for (Map.Entry<RequestMappingInfo, HandlerMethod> m : map.entrySet()) {
            RequestMappingInfo info = m.getKey();
            HandlerMethod method = m.getValue();
            PatternsRequestCondition p = info.getPatternsCondition();
            if (p != null) {
                for (String url : p.getPatterns()) {
                    // 匹配了接口名之后，才往结果map中存放接口信息
                    if (url.equals(interfaceName)) {
                        result.put("url", url);
                        // 反射获取url对应类名和方法名
                        // 类名
                        result.put("className", method.getMethod().getDeclaringClass().getName());
                        // 方法名
                        result.put("method", method.getMethod());
                        // 获取请求类型
                        RequestMethodsRequestCondition methodsRequestCondition = info.getMethodsCondition();
                        for (RequestMethod requestMethod : methodsRequestCondition.getMethods()) {
                            result.put("type", requestMethod.toString());
                        }
                        break a;
                    }
                }
            }
        }
        return result;
    }

    /**
     * Description: 保存病历模板
     * Param: [list]
     * return: void
     * Author: tong-aj
     * Date: 2021/2/25
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveWdEditors(List<WdEditorVo> list) {

        // 验证modelName不能重复
        String modelName = list.get(0).getWdeditorDsset().getModelName();
        String modelId = list.get(0).getWdeditorDsset().getModelId();
        if (StringUtils.isNotEmpty(modelName)) {
            List<WdeditorDsset> models = wdeditorDssetMapper
                    .selectList(
                            new QueryWrapper<WdeditorDsset>()
                                    .eq(ServiceConstant.MODEL_NAME, modelName)
                                    .ne(ServiceConstant.MODEL_ID, modelId)
                    );
            if (!CollectionUtils.isEmpty(models)) {
                throw new CustomException("该（" + modelName + "）模板名称已存在");
            }
        }


        // 先删除原来所有的modelId下的模板设计信息
        List<String> modelIds = list.stream().map(e -> e.getWdeditorDsset().getModelId()).distinct().collect(Collectors.toList());
        if (modelIds.size() == 1) {
            recordUseMapper.deleteModelData(modelIds.get(0));
        }

        List<WdeditorDsset> insertSetList = new ArrayList<>();
        List<WdeditorDssetStatic> insertStaticList = new ArrayList<>();
        List<WdeditorDssetLoad> insertLoadList = new ArrayList<>();
        List<WdeditorDssetStorge> insertStorageList = new ArrayList<>();
        List<WdeditorDssetProperty> insertPropertyList = new ArrayList<>();

        list.forEach(wdEditorVo -> {
            String setId = idUtils.getNextVal(OracleSequenceEnum.SEQ_ID_WDEDITOR_DSSET.getCode()).toString();
            wdEditorVo.getWdeditorDsset().setSetId(setId);
            wdEditorVo.getWdeditorDsset().setModelPath(WdEditorHtmlUtils.getHtmlDirFile() + File.separator + wdEditorVo.getWdeditorDsset().getModelId());
            insertSetList.add(wdEditorVo.getWdeditorDsset());

            // 存储静态数据
            if (wdEditorVo.getWdeditorDsStaic() != null) {
                String dIdStatic = wdEditorVo.getWdeditorDsStaic().getDId();
                String staticShowField = wdEditorVo.getStaticShowField();
                String staticStorageField = wdEditorVo.getStaticStorageField();
                if (StringUtils.isNotEmpty(staticShowField) &&
                        StringUtils.isNotEmpty(staticStorageField)) {
                    WdeditorDssetStatic wdeditorDssetStatic = new WdeditorDssetStatic(setId, dIdStatic, staticShowField, staticStorageField);
                    insertStaticList.add(wdeditorDssetStatic);
                }
            }

            String readField = wdEditorVo.getReadField();
            // 让前台传dId
            String readGroupId = wdEditorVo.getReadGroupId();
            if (StringUtils.isNotEmpty(readField) && StringUtils.isNotEmpty(readGroupId)) {
                WdeditorDssetLoad wdeditorDssetLoad = new WdeditorDssetLoad(setId, readGroupId, readField, readGroupId);
                insertLoadList.add(wdeditorDssetLoad);
            }

            // 数据源配置表_存储
            String storageName = wdEditorVo.getStorageName();
            String storageParameter = wdEditorVo.getStorageParameter();
            if (StringUtils.isNotEmpty(storageName) && StringUtils.isNotEmpty(storageParameter)) {
                WdeditorDssetStorge wdeditorDssetStorge = new WdeditorDssetStorge(setId, storageName, storageParameter);
                insertStorageList.add(wdeditorDssetStorge);
            }

            // 数据源配置表_属性
            String defaultValue = wdEditorVo.getDefaultValue();
            Long minInclusive = wdEditorVo.getMinInclusive();
            Long maxInclusive = wdEditorVo.getMaxInclusive();
            if (StringUtils.isNotEmpty(defaultValue)) {
                WdeditorDssetProperty wdeditorDssetProperty = new WdeditorDssetProperty(setId, defaultValue, minInclusive, maxInclusive);
                insertPropertyList.add(wdeditorDssetProperty);
            }
            // 存储自定义
            List<String> customValues = wdEditorVo.getCustomValues();
            if (!CollectionUtils.isEmpty(customValues)) {
                saveWdeditorDssetCustom(setId, customValues);
            }

            // 修改历史
            if (!CollectionUtils.isEmpty(wdEditorVo.getWdeditorHistoryList())) {
                List<WdeditorHistory> wdeditorHistoryList = wdEditorVo.getWdeditorHistoryList();
                wdeditorHistoryList.forEach(history -> {
                    history.setSetId(setId);
                    history.setUpdateTime(new Date());
                });
                wdeditorHistoryService.saveBatch(wdEditorVo.getWdeditorHistoryList());
            }
        });

        if (!CollectionUtils.isEmpty(insertSetList)) {
            wdeditorDssetService.saveBatch(insertSetList);
        }
        if (!CollectionUtils.isEmpty(insertStaticList)) {
            wdeditorDssetStaticService.saveBatch(insertStaticList);
        }
        if (!CollectionUtils.isEmpty(insertLoadList)) {
            wdeditorDssetLoadService.saveBatch(insertLoadList);
        }
        if (!CollectionUtils.isEmpty(insertStorageList)) {
            wdeditorDssetStorgeService.saveBatch(insertStorageList);
        }
        if (!CollectionUtils.isEmpty(insertPropertyList)) {
            wdeditorDssetPropertyService.saveBatch(insertPropertyList);
        }
    }

    /**
     * Description: 存储自定义
     * Param: [setId, customValues]
     * return: void
     * Author: tong-aj
     * Date: 2021/2/25
     */
    private void saveWdeditorDssetCustom(String setId, List<String> customValues) {
        wdeditorDssetCustomService.remove(new QueryWrapper<WdeditorDssetCustom>().eq(ServiceConstant.SET_ID, setId));
        List<WdeditorDssetCustom> insertList = new ArrayList<>();
        for (String customValue : customValues) {
            String idx = idUtils.getNextVal(OracleSequenceEnum.SEQ_ID_WDEDITOR_DSSET_CUSTOM.getCode()).toString();
            Long idxLong = Long.parseLong(idx);
            WdeditorDssetCustom wdeditorDssetCustom = new WdeditorDssetCustom(setId, idxLong, customValue);
            insertList.add(wdeditorDssetCustom);
        }
        wdeditorDssetCustomService.saveBatch(insertList);
    }

    /**
     * Description: 保存模板Html信息
     * Param: [wdEditorsHtmlVo]
     * return: void
     * Author: tong-aj
     * Date: 2021/2/25
     */
    @Override
    public void saveWdEditorsHtml(WdEditorsHtmlVo wdEditorsHtmlVo) {

        String htmlValue = wdEditorsHtmlVo.getHtmlValue();

        // 拿到文件名
        String filename = wdEditorsHtmlVo.getModelId();

        // 存放上传图片的文件夹
        File fileDir = WdEditorHtmlUtils.getHtmlDirFile();

        // 构建真实的文件路径
        File newFile = new File(fileDir.getAbsolutePath() + File.separator + filename);
        try (BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(newFile))) {
            bufferedWriter.write(htmlValue);
            bufferedWriter.flush();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Description: 获取模板Html数据
     * Param: [modelId]
     * return: com.wonders.hisdoctor.station.project.record.vo.WdEditorsHtmlVo
     * Author: tong-aj
     * Date: 2021/3/9
     */
    @Override
    public WdEditorsHtmlVo getWdEditorsHtml(String modelId) {
        // 存放上传图片的文件夹
        File fileDir = WdEditorHtmlUtils.getHtmlDirFile();

        // 构建真实的文件路径
        File file = new File(fileDir.getAbsolutePath() + File.separator + modelId);

        WdEditorsHtmlVo wdEditorsHtmlVo = new WdEditorsHtmlVo();
        if (!file.exists()) {
            try {
                Class clazz = Class.forName("com.wonders.hisdoctor.station.constant.HtmlConstant");
                Field[] declaredFields = clazz.getDeclaredFields();
                for (Field field : declaredFields) {
                    if (modelId.equals(field.getName().replace("html_", ""))) {
                        wdEditorsHtmlVo.setModelId(modelId);
                        String htmlValue = (String) field.get(clazz);
                        wdEditorsHtmlVo.setHtmlValue(htmlValue);
                        try (BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(file))) {
                            bufferedWriter.write(htmlValue);
                            bufferedWriter.flush();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            try (BufferedReader bufferedReader = new BufferedReader(new FileReader(file))) {
                String result;
                StringBuilder stringBuffer = new StringBuilder();
                while ((result = bufferedReader.readLine()) != null) {
                    stringBuffer.append(result);
                }
                wdEditorsHtmlVo.setModelId(modelId);
                wdEditorsHtmlVo.setHtmlValue(stringBuffer.toString());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return wdEditorsHtmlVo;
    }


    /**
     * Description: 根据modelId查询所有模板控件数据
     * Param: [modelId, patientId, visitNo, visitDate]
     * return: java.util.List<com.wonders.hisdoctor.station.project.record.vo.ClassIdValue>
     * Author: tong-aj
     * Date: 2021/3/9
     */
    @Override
    public List<WdEditorVo> getWdEditorsByModelId(String modelId, String patientId, String visitNo, Date visitDate, String tId, String empNo, HttpServletRequest request) {

        // 准备所有模板主数据源
        List<WdeditorDsset> allWdEditorDsSet = wdeditorDssetMapper.selectList(new QueryWrapper<WdeditorDsset>().eq(ServiceConstant.MODEL_ID, modelId));

        // 如果主表集合为空，直接返回
        if (CollectionUtils.isEmpty(allWdEditorDsSet)) {
            return new ArrayList<>();
        }
        // 定义返回对象
        List<WdEditorVo> result = new ArrayList<>(allWdEditorDsSet.size());

        // 将获取的所有SET_ID 放入相应的集合中
        List<String> allSetIds = allWdEditorDsSet.stream().map(WdeditorDsset::getSetId).collect(Collectors.toList());

        // 所有读取数据源
        List<WdeditorDssetLoad> allLoads = wdeditorDssetLoadMapper.selectList(new QueryWrapper<WdeditorDssetLoad>().in(ServiceConstant.SET_ID, allSetIds));

        // 所有静态数据源
        List<WdeditorDssetStatic> allStatics = wdeditorDssetStaticMapper.selectList(new QueryWrapper<WdeditorDssetStatic>().in(ServiceConstant.SET_ID, allSetIds));

        // 所有接口数据
        List<WdeditorDssetStorge> allStorages = wdeditorDssetStorgeMapper.selectList(new QueryWrapper<WdeditorDssetStorge>().in(ServiceConstant.SET_ID, allSetIds));

        // 所有控件的自定义内容
        List<WdeditorDssetCustom> allCustoms = wdeditorDssetCustomMapper.selectList(new QueryWrapper<WdeditorDssetCustom>().in(ServiceConstant.SET_ID, allSetIds));

        // 所有控件的属性配置
        List<WdeditorDssetProperty> allProperties = wdeditorDssetPropertyMapper.selectList(new QueryWrapper<WdeditorDssetProperty>().in(ServiceConstant.SET_ID, allSetIds));

        // 所有控件的历史数据
        List<WdeditorHistory> allHistories = wdeditorHistoryMapper.selectList(new QueryWrapper<WdeditorHistory>().in(ServiceConstant.SET_ID, allSetIds));

        // 获得所有用到的业务表
        List<WdeditorDs> allDs = wdeditorDsMapper.selectList(new QueryWrapper<WdeditorDs>().eq(ServiceConstant.TABLE_TYPE, ServiceConstant.ONE_STRING));
        List<WdeditorDs> allDiagDs = wdeditorDsMapper.selectList(new QueryWrapper<WdeditorDs>().eq(ServiceConstant.TABLE_TYPE, ServiceConstant.TWO_STRING));
        List<WdeditorDs> allEzDs = wdeditorDsMapper.selectList(new QueryWrapper<WdeditorDs>().eq(ServiceConstant.TABLE_TYPE, ServiceConstant.THREE_STRING));


        // 使用的静态数据表主键
        List<String> staticDids = allStatics.stream().map(WdeditorDssetStatic::getDId).distinct().collect(Collectors.toList());

        // 获得静态数据源表
        List<WdeditorDs> allDsStatic = wdeditorDsMapper.selectList(new QueryWrapper<WdeditorDs>().in(ServiceConstant.D_ID, staticDids));

        // 获取所有简单数据字典表的did
        List<String> ezDids = allEzDs.stream().map(WdeditorDs::getDId).collect(Collectors.toList());
        List<WdeditorDssetStatic> allEzStatics = new ArrayList<>();
        allStatics.forEach(e -> {
            if (ezDids.contains(e.getDId())) {
                allEzStatics.add(e);
            }
        });


        // 使用的静态数据表主键
        List<String> staticEzDids = allEzStatics.stream().map(WdeditorDssetStatic::getDId).distinct().collect(Collectors.toList());

        // 存放setId和复杂静态数据结果集
        //final Map<String, List<Map<String, Object>>> setIdStaticDataResult = dealWithStaticDataList(allStatics, staticDids);
        final Map<String, List<Map<String, Object>>> setIdStaticDataResult = dealWithStaticDataList(allEzStatics, staticEzDids);

        // 循环赋值控件数据
        allSetIds.forEach(setId -> {
            // 定义控件数据对象
            WdEditorVo wdEditorVo = new WdEditorVo();
            // 过滤获取主表数据：setId相同
            Optional<WdeditorDsset> wdEditorDsSet = allWdEditorDsSet.stream().filter(dsSet -> dsSet.getSetId().equals(setId)).findFirst();
            // 存入控件数据对象
            wdEditorVo.setWdeditorDsset(wdEditorDsSet.orElse(null));

            // 过滤获取存储业务接口数据：setId相同
            Optional<WdeditorDssetStorge> wdEditorStorage = allStorages.stream().filter(storage -> storage.getSetId().equals(setId)).findFirst();
            // 赋值业务接口数据
            wdEditorStorage.ifPresent(setStorage -> {
                wdEditorVo.setStorageName(setStorage.getStorageName());
                wdEditorVo.setStorageParameter(setStorage.getStorageParameter());
            });

            // 过滤获取静态数据：setId相同
            Optional<WdeditorDssetStatic> wdEditorStatics = allStatics.stream().filter(setStatic -> setStatic.getSetId().equals(setId)).findFirst();
            // 赋值静态数据
            wdEditorStatics.ifPresent(setStatic -> {
                String dId = setStatic.getDId();
                if (!CollectionUtils.isEmpty(allDsStatic)) {
                    Optional<WdeditorDs> wdEditorDs = allDsStatic.stream().filter(e -> e.getDId().equals(dId)).findFirst();
                    wdEditorVo.setWdeditorDsStaic(wdEditorDs.orElse(null));
                }
                wdEditorVo.setStaticStorageField(setStatic.getStaticStorageField());
                wdEditorVo.setStaticShowField(setStatic.getStaticShowField());
            });

            // 过滤获取读取业务表数据：setId相同
            Optional<WdeditorDssetLoad> setLoad = allLoads.stream().filter(load -> load.getSetId().equals(setId)).findAny();
            // 赋值
            setLoad.ifPresent(load -> {
                wdEditorVo.setReadField(setLoad.get().getReadField());
                wdEditorVo.setReadGroupId(setLoad.get().getReadGroupId());
            });

            // 过滤获取控件自定义值：setId相同
            List<WdeditorDssetCustom> collects = allCustoms.stream().filter(custom -> custom.getSetId().equals(setId)).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(collects)) {
                // 赋值
                wdEditorVo.setCustomValues(collects.stream().map(WdeditorDssetCustom::getCustomValue).collect(Collectors.toList()));
                // 过滤控件属性值：setId相同
                Optional<WdeditorDssetProperty> setProperty = allProperties.stream().filter(property -> property.getSetId().equals(setId)).findAny();
                // 赋值
                setProperty.ifPresent(property -> {
                    wdEditorVo.setMaxInclusive(property.getMaxInclusive());
                    wdEditorVo.setMinInclusive(property.getMinInclusive());
                    wdEditorVo.setDefaultValue(property.getDefaultValue());
                });
            }

            // 过滤获取控件历史数据：：setId相同
            /*List<WdeditorHistory> histories = allHistories.stream().filter(history -> history.getSetId().equals(setId)).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(histories)) {
                wdEditorVo.setWdeditorHistoryList(histories);
            }*/

            // 赋值静态数据集合
            if (setIdStaticDataResult != null && setIdStaticDataResult.containsKey(setId)) {
                wdEditorVo.setStaticDataList(setIdStaticDataResult.get(setId));
            }

            // 将控件数据对象放入返回集合中
            result.add(wdEditorVo);
        });
        // 特殊处理
        String hospitalCode = "";
        // 获取当前登录人信息，得到医生姓名和机构名称
        LoginUserDTO loginUserDTO = tokenService.getLoginUserDTO(tokenService.getToken(request));
        if (loginUserDTO != null) {
            hospitalCode = loginUserDTO.getSysSysuserVo().getHospitalCode();
        }
        // 判断是查询病历，还是查询病历模板
        if (StringUtils.isNotEmpty(tId)) {
            dealWithModelTempalte(tId, result);
        } else {
            // 根据请求的病人就诊参数，查询病历表业务数据，并各自赋值各自的控件中
            dealWithModelData(patientId, visitNo, visitDate, allWdEditorDsSet, result, allSetIds, allLoads, allDs, empNo);

            // 特殊处理，给特殊的控件赋值
            getDoctorAndHospital(hospitalCode, empNo, patientId, result);
            // 诊断合并的特殊处理
            tmDiagHandler(patientId, visitNo, visitDate, empNo, hospitalCode, result);
        }
        return result;
    }

    @Autowired
    private OutpMrMapper outpMrMapper;

    @Autowired
    private WdeditorSupportMapper supportMapper;

    /**
     * Description: 诊断合并的特殊处理,查询该病历是否
     * Param: [patientId, visitNo, visitDate, empNo]
     * return: void
     * Author: tong-aj
     * Date: 2021/7/27
     */
    private void tmDiagHandler(String patientId, String visitNo, Date visitDate, String empNo, String hospitalCode, List<WdEditorVo> result) {
        OutpMr outpMr = outpMrMapper.selectOne(new QueryWrapper<OutpMr>()
                .eq(ServiceConstant.PATIENT_ID, patientId)
                .eq(ServiceConstant.VISIT_DATE, visitDate)
                .eq(ServiceConstant.VISIT_NO, visitNo)
                .eq(ServiceConstant.DOCTOR, empNo));
        if (outpMr != null) {
            WdEditorVo wdEditorVo = new WdEditorVo();
            if (StringUtils.isNotEmpty(outpMr.getTmDiagCode())) {
                wdEditorVo.setClassIdValue(outpMr.getTmDiagCode());
            }
            String tmDiagCodeColumn = commonUtil.getFieldColumn(OutpMr.class, "tmDiagCode");
            String tmDiagDescColumn = commonUtil.getFieldColumn(OutpMr.class, "tmDiagDesc");
            wdEditorVo.setReadField(tmDiagCodeColumn);
            wdEditorVo.setStaticShowField(tmDiagDescColumn);
            wdEditorVo.setStaticStorageField(tmDiagCodeColumn);
            wdEditorVo.setWdeditorDsset(new WdeditorDsset().setSetId(tmDiagDescColumn));
            result.add(wdEditorVo);

            WdEditorVo wdEditorTypeVo = new WdEditorVo();
            if (StringUtils.isNotEmpty(outpMr.getTmTypeCode())) {
                wdEditorTypeVo.setClassIdValue(outpMr.getTmTypeCode());
            }
            String tmTypeCodeColumn = commonUtil.getFieldColumn(OutpMr.class, "tmTypeCode");
            String tmTypeDescColumn = commonUtil.getFieldColumn(OutpMr.class, "tmTypeDesc");
            wdEditorTypeVo.setReadField(tmTypeCodeColumn);
            wdEditorTypeVo.setStaticShowField(tmTypeDescColumn);
            wdEditorTypeVo.setStaticStorageField(tmTypeCodeColumn);
            wdEditorTypeVo.setWdeditorDsset(new WdeditorDsset().setSetId(tmTypeDescColumn));
            result.add(wdEditorTypeVo);
        }
        WdeditorSupport wdeditorSupport = supportMapper.selectOne(new QueryWrapper<WdeditorSupport>()
                .eq(ServiceConstant.PATIENT_ID, patientId)
                .eq(ServiceConstant.VISIT_DATE, visitDate)
                .eq(ServiceConstant.VISIT_NO, visitNo)
                .eq(ServiceConstant.DOCTOR, empNo));
        if (wdeditorSupport != null) {
            // 匹配控件，赋值
            result.forEach(wdEditorVo -> {
                if (wdEditorVo.getReadField().equals(ServiceConstant.ORDINAL) && wdEditorVo.getReadGroupId().equals(ServiceConstant.OUTP_MR)) {
                    wdEditorVo.setClassIdValue(wdeditorSupport.getTitle());
                }
            });
        } else {
            // 匹配控件，赋值
            result.forEach(wdEditorVo -> {
                if (wdEditorVo.getReadField().equals(ServiceConstant.ORDINAL) && wdEditorVo.getReadGroupId().equals(ServiceConstant.OUTP_MR)) {
                    wdEditorVo.setClassIdValue(commonUtil.setPrintTitle(hospitalCode));
                }
            });
        }
    }

    /**
     * Description: 处理：存在templateName，走病历模板，查询set-》defaultValue，并将result中每个对象的classIdValue进行相应的赋值
     * Param: [templateName, result]
     * return: void
     * Author: tong-aj
     * Date: 2021/4/14
     */
    private void dealWithModelTempalte(String tId, List<WdEditorVo> result) {
        List<WdeditorPritemplatedetail> details = wdeditorPritemplatedetailMapper.selectList(new QueryWrapper<WdeditorPritemplatedetail>().eq("t_id", tId));
        if (CollectionUtils.isEmpty(details)) {
            return;
        }
        details.forEach(detail -> result.forEach(wdEditorVo -> {
            if (wdEditorVo.getWdeditorDsset().getSetId().equals(detail.getSetId())) {
                wdEditorVo.setClassIdValue(detail.getDefaultValue());
            }
        }));
    }

    /**
     * Description: 处理静态数据集合
     * Param: [allStatics, staticDIds, setIdStaticData]
     * return: java.util.Map<java.lang.String,java.util.List<java.util.Map<java.lang.String,java.lang.Object>>>
     * Author: tong-aj
     * Date: 2021/3/10
     */
    private Map<String, List<Map<String, Object>>> dealWithStaticDataList(List<WdeditorDssetStatic> allStatics, List<String> staticDIds) {
        if (!CollectionUtils.isEmpty(staticDIds)) {
            // 通过所有静态数据源表主键查询所有静态表数据源
            List<WdeditorDs> allStatic = wdeditorDsMapper.selectList(new QueryWrapper<WdeditorDs>().in(ServiceConstant.D_ID, staticDIds));

            Map<String, List<Map<String, Object>>> finalSetIdStaticData = new HashMap<>(allStatic.size());
            allStatic.forEach(editorDs -> {
                // 获取表名
                String tableName = editorDs.getTableName();
                // 获取did
                String dId = editorDs.getDId();
                // 过滤获取静态数据
                Optional<WdeditorDssetStatic> dsSetStatic = allStatics.stream().filter(setStatic -> setStatic.getDId().equals(dId)).findFirst();
                if (dsSetStatic.isPresent()) {
                    WdeditorDssetStatic wdEditorDsSetStatic = dsSetStatic.get();
                    String staticShowField = wdEditorDsSetStatic.getStaticShowField();
                    String staticStorageField = wdEditorDsSetStatic.getStaticStorageField();
                    List<Map<String, Object>> staticDataListFromDB = recordUseMapper.getStaticData(tableName, staticShowField, staticStorageField);
                    if (staticDataListFromDB != null && !CollectionUtils.isEmpty(staticDataListFromDB)) {
                        redisCache.setCacheObject(tableName, staticDataListFromDB, expireTime, TimeUnit.HOURS);
                        finalSetIdStaticData.put(wdEditorDsSetStatic.getSetId(), staticDataListFromDB);
                    }
                    /*// 查询字典表数量
                    int count = recordUseMapper.getTableCounts(tableName);
                    // 查询redis是否存在tableCount
                    if (redisCache.getCacheObject(tableName + ServiceConstant.COUNT) == null) {
                        // 不存在则插入
                        dealWithRedis(finalSetIdStaticData, tableName, wdEditorDsSetStatic, count);
                    } else {
                        // 查询redis缓存的字典表数量
                        int cacheCount = redisCache.getCacheObject(tableName + ServiceConstant.COUNT);
                        // 存在 判断数量是否一样
                        if (cacheCount == count) {
                            // 再取一次，确保没有静态数据源
                            if (redisCache.getCacheObject(tableName) == null) {
                                dealWithRedis(finalSetIdStaticData, tableName, wdEditorDsSetStatic, count);
                            }
                            // 如果一样，无需更新redis，直接获取
                            List<Map<String, Object>> staticDataList = redisCache.getCacheObject(tableName);
                            finalSetIdStaticData.put(wdEditorDsSetStatic.getSetId(), staticDataList);
                        } else {
                            // 将新的数量存入redis
                            dealWithRedis(finalSetIdStaticData, tableName, wdEditorDsSetStatic, count);
                        }
                    }*/
                }
            });
            return finalSetIdStaticData;
        }
        return null;
    }

    @Value("${token.expireTime}")
    private int expireTime;

    /**
     * Description: 处理redis部分
     * Param: [finalSetIdStaticData, tableName, wdEditorDsSetStatic, count]
     * return: void
     * Author: tong-aj
     * Date: 2021/3/10
     */
    private void dealWithRedis(Map<String, List<Map<String, Object>>> finalSetIdStaticData, String tableName, WdeditorDssetStatic wdEditorDsSetStatic, int count) {
        redisCache.setCacheObject(tableName + ServiceConstant.COUNT, count, expireTime, TimeUnit.HOURS);
        // 如果不一样，则tableCount和tableData都需要更新
        String staticShowField = wdEditorDsSetStatic.getStaticShowField();
        String staticStorageField = wdEditorDsSetStatic.getStaticStorageField();
        List<Map<String, Object>> staticDataListFromDB = recordUseMapper.getStaticData(tableName, staticShowField, staticStorageField);
        if (staticDataListFromDB != null && !CollectionUtils.isEmpty(staticDataListFromDB)) {
            redisCache.setCacheObject(tableName, staticDataListFromDB, expireTime, TimeUnit.HOURS);
            finalSetIdStaticData.put(wdEditorDsSetStatic.getSetId(), staticDataListFromDB);
        }
    }

    /**
     * Description: 根据请求的病人就诊参数，查询病历表业务数据，并各自赋值各自的控件中
     * Param: [patientId, visitNo, visitDate, allWdEditorDsSet, result, allSetIds, allLoads, allDs]
     * return: void
     * Author: tong-aj
     * Date: 2021/3/10
     */
    private void dealWithModelData(String patientId, String visitNo, Date visitDate, List<WdeditorDsset> allWdEditorDsSet, List<WdEditorVo> result, List<String> allSetIds, List<WdeditorDssetLoad> allLoads, List<WdeditorDs> allDs, String empNo) {
        if (StringUtils.isNotEmpty(patientId) && StringUtils.isNotEmpty(visitNo) && visitDate != null) {
            ModelDataBo modelDataBo = new ModelDataBo();
            modelDataBo.setPatientId(patientId);
            modelDataBo.setVisitNo(visitNo);
            modelDataBo.setVisitDate(visitDate);
            modelDataBo.setAllLoads(allLoads);
            modelDataBo.setEmpNo(empNo);
            // 定义SetId和classId的对应关系map
            Map<String, String> classIdSetId = new HashMap<>(allSetIds.size());
            allWdEditorDsSet.forEach(model -> classIdSetId.put(model.getSetId(), model.getClassId()));
            modelDataBo.setClassIdSetId(classIdSetId);
            modelDataBo.setAllDs(allDs);

            List<ClassIdValue> dataModel = getModelData(modelDataBo);
            if (!CollectionUtils.isEmpty(dataModel)) {
                result.forEach(wdEditorVo -> dataModel.forEach(e -> {
                    if (e.getClassId().equals(wdEditorVo.getWdeditorDsset().getClassId())) {
                        wdEditorVo.setClassIdValue(e.getValue());
                    }
                }));
            }
        }
    }


    /**
     * Description: 根据modelId读取业务表/视图数据
     * Param: [modelDataBo]
     * return: java.util.List<com.wonders.hisdoctor.station.project.record.vo.ClassIdValue>
     * Author: tong-aj
     * Date: 2021/3/10
     */
    private List<ClassIdValue> getModelData(ModelDataBo modelDataBo) {
        String patientId = modelDataBo.getPatientId();
        Date visitDate = modelDataBo.getVisitDate();
        String visitNo = modelDataBo.getVisitNo();
        String empNo = modelDataBo.getEmpNo();

        Map<String, String> classIdSetId = modelDataBo.getClassIdSetId();

        // 将所有业务字段和classId做绑定
        List<WdeditorDssetLoad> loads = modelDataBo.getAllLoads();
        loads.forEach(load -> {
            if (classIdSetId.containsKey(load.getSetId())) {
                classIdSetId.put(load.getReadField(), classIdSetId.get(load.getSetId()));
            }
        });
        // 获得去重后，所有用到的业务表
        List<WdeditorDs> allDs = modelDataBo.getAllDs();
        List<String> dataTables = loads.stream().map(WdeditorDssetLoad::getReadGroupId).distinct().collect(Collectors.toList());

        List<String> useDataTables = new ArrayList<>();

        dataTables.forEach(table -> allDs.forEach(type -> {
            if (table.equals(type.getTableName())) {
                useDataTables.add(table);
            }
        }));

        Map<String, Object> resultMap = new HashMap<>();

        useDataTables.forEach(dataTable -> {
            // 循环业务表,组装column语句
            StringBuilder sqlColumns = new StringBuilder();
            // 循环业务表组装table语句
            StringBuilder sqlTables = new StringBuilder();
            // 循环业务表组装where语句
            StringBuilder sqlWhere = new StringBuilder();
            // 如果业务数据中，该字段的分类等于业务表
            loads.forEach(load -> {
                if (load.getReadGroupId().equals(dataTable)) {
                    sqlColumns.append(dataTable).append(".").append(load.getReadField()).append(",");
                }
            });
            String visitDateStr = DateUtils.formatDate(visitDate, DateUtils.YYYYMMDD);
            sqlTables.append(dataTable).append(",");
            if (dataTable.equals(ServiceConstant.CLINIC_MASTER)) {
                sqlWhere.append(" CLINIC_MASTER.patient_id='").append(patientId).append("'")
                        .append(" and CLINIC_MASTER.visit_no='").append(visitNo).append("'")
                        .append(" and CLINIC_MASTER.visit_date=").append("to_date('").append(visitDateStr).append("','yyyy/MM/dd')").append(" and");
            } else if (dataTable.equals(ServiceConstant.OUTP_MR)) {
                sqlWhere.append(" OUTP_MR.patient_id='").append(patientId).append("'")
                        .append(" and OUTP_MR.visit_no='").append(visitNo).append("'")
                        .append(" and OUTP_MR.doctor='").append(empNo).append("'")
                        .append(" and OUTP_MR.visit_date=").append("to_date('").append(visitDateStr).append("','yyyy/MM/dd')").append(" and");
            }
            // 截取
            String columnStr = sqlColumns.toString();
            if (StringUtils.isNotEmpty(columnStr)) {
                columnStr = columnStr.substring(0, columnStr.length() - 1);
            }

            // 截取
            String tableStr = sqlTables.toString();
            if (StringUtils.isNotEmpty(tableStr)) {
                tableStr = tableStr.substring(0, tableStr.length() - 1);
            }

            // 截取
            String whereStr = sqlWhere.toString();
            if (StringUtils.isNotEmpty(whereStr)) {
                whereStr = "where " + whereStr.substring(0, whereStr.length() - 3);
            }
            // 组装sql语句进行查询
            if (StringUtils.isNotEmpty(columnStr) && StringUtils.isNotEmpty(tableStr)) {
                Map<String, Object> columnValue = recordUseMapper.getTableData(columnStr, tableStr, whereStr);
                if (columnValue != null && columnValue.size() > 0) {
                    resultMap.putAll(columnValue);
                }
            }
        });

        List<ClassIdValue> result = new ArrayList<>();

        // 循环map，将column相等的classId和value封装进ClassIdValue对象
        if (resultMap.size() > 0) {

            for (Map.Entry<String, Object> stringObjectEntry : resultMap.entrySet()) {
                String key = (stringObjectEntry).getKey();
                Object value = (stringObjectEntry).getValue();
                if (value instanceof Date) {
                    value = DateUtils.dateFormatTime((Date) value, "yyyy/MM/dd");
                }
                //判断classId 中的Value 是否在Column
                if (classIdSetId.containsKey(key)) {
                    ClassIdValue classIdValue = new ClassIdValue(classIdSetId.get(key), value);
                    result.add(classIdValue);
                }
            }
        }
        return result;
    }

    /**
     * Description: 特殊处理，给特殊的控件赋值
     * Param: [request, result]
     * return: void
     * Author: tong-aj
     * Date: 2021/3/10
     */
    private void getDoctorAndHospital(String hospitalCode, String empNo, String patientId, List<WdEditorVo> result) {

        // 根据patientId获取DATE_OF_BIRTH
        PatMasterIndex patMasterIndex = patMasterIndexMapper.selectOne(new QueryWrapper<PatMasterIndex>().eq(ServiceConstant.PATIENT_ID, patientId));
        Date dateOfBirth = patMasterIndex.getDateOfBirth();
        String formatTime = DateUtils.dateFormatTime(dateOfBirth, DateUtils.YYYY_MM_DD);
        String ageStr = CountAgeUtil.getAgeStr(formatTime);

        String hospitalName = "";
        if (StringUtils.isNotEmpty(hospitalCode)) {
            HospitalDict hospitalDict = hospitalDictMapper.selectOne(new QueryWrapper<HospitalDict>().eq(ServiceConstant.HOSPITAL_CODE, hospitalCode));
            hospitalName = hospitalDict.getHospitalName();
        }

        String finalHospitalName = hospitalName;
        // 匹配控件，赋值
        result.forEach(wdEditorVo -> {
            if (wdEditorVo.getReadField().equals(ServiceConstant.VISIT_NO) && wdEditorVo.getReadGroupId().equals(ServiceConstant.OUTP_MR)) {
                wdEditorVo.setClassIdValue(finalHospitalName);
            }
            if (wdEditorVo.getReadField().equals(ServiceConstant.DOCTOR) && wdEditorVo.getReadGroupId().equals(ServiceConstant.OUTP_MR)) {
                if (wdEditorVo.getClassIdValue() == null) {
                    wdEditorVo.setClassIdValue(empNo);
                }
                if (!CollectionUtils.isEmpty(wdEditorVo.getStaticDataList())) {
                    wdEditorVo.getStaticDataList().removeIf(e -> !e.get(ServiceConstant.EMP_NO).equals(empNo));
                }
            }
            if (wdEditorVo.getReadField().equals(ServiceConstant.SEX) && !CollectionUtils.isEmpty(wdEditorVo.getStaticDataList())) {
                wdEditorVo.getStaticDataList().removeIf(e -> !e.get(ServiceConstant.SEX_NAME).equals(wdEditorVo.getClassIdValue()));
            }
            if (wdEditorVo.getReadField().equals(ServiceConstant.VISIT_DEPT) && !CollectionUtils.isEmpty(wdEditorVo.getStaticDataList())) {
                wdEditorVo.getStaticDataList().removeIf(e -> !e.get(ServiceConstant.DEPT_CODE).equals(wdEditorVo.getClassIdValue()));
            }
            if (wdEditorVo.getReadField().equals(ServiceConstant.AGE) && wdEditorVo.getReadGroupId().equals(ServiceConstant.CLINIC_MASTER)) {
                wdEditorVo.setClassIdValue(ageStr);
            }
        });
    }

    /**
     * Description: 根据医疗机构代码合模板查询字段查询所有Model
     * Param: [hospitalCode, fastFind]
     * return: java.util.List<com.wonders.hisdoctor.station.project.base.domain.WdeditorDsset>
     * Author: tong-aj
     * Date: 2021/3/12
     */
    @Override
    public List<Map<String, Object>> getModelList(String hospitalCode, String fastFind) {
        return recordUseMapper.getModelList(hospitalCode, fastFind);
    }

    @Override
    public void deleteModels(List<String> modelIds) {
        recordUseMapper.deleteModels(modelIds);
    }

    @Override
    public void saveHistories(List<WdeditorHistory> list) {
        wdeditorHistoryService.saveBatch(list);
    }

    /**
     * Description: 通过机构代码，医生工号和个人模板名称查询个人模板数据
     * Param: [hospitalCode, operator, templateName]
     * return: java.util.List<com.wonders.hisdoctor.station.project.base.domain.WdeditorPritemplatedetail>
     * Author: tong-aj
     * Date: 2021/3/24
     */
    @Override
    public List<WdeditorPritemplatedetail> getTemplateDetails(String orgId, String operate, String templateName) {
        // 根据条件查询个人模板主表数据
        QueryWrapper<WdeditorPritemplatemaster> masterQuery = new QueryWrapper<WdeditorPritemplatemaster>().eq(ServiceConstant.TEMPLATE_NAME, templateName).eq(ServiceConstant.OPERATE, operate).eq(ServiceConstant.ORG_ID, orgId);
        WdeditorPritemplatemaster master = wdeditorPritemplatemasterMapper.selectOne(masterQuery);
        if (master != null) {
            // 找到主表数据，获取tid
            String tId = master.getTId();
            // 根据tid查询明细数据，并返回
            QueryWrapper<WdeditorPritemplatedetail> detailQuery = new QueryWrapper<WdeditorPritemplatedetail>().eq(ServiceConstant.T_ID, tId);
            List<WdeditorPritemplatedetail> details = wdeditorPritemplatedetailMapper.selectList(detailQuery);
            if (!CollectionUtils.isEmpty(details)) {
                return details;
            }
        }
        return new ArrayList<>();
    }

    /**
     * Description: 保存个人模板数据
     * Param: [templateVo]
     * return: void
     * Author: tong-aj
     * Date: 2021/3/24
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveTemplates(TemplateVo templateVo) {
        if (templateVo != null) {

            String templateName = templateVo.getWdeditorPritemplatemaster().getTemplateName();
            String effectiveDept = templateVo.getWdeditorPritemplatemaster().getEffectiveDept();
            String orgId = templateVo.getWdeditorPritemplatemaster().getOrgId();
            String tId = templateVo.getWdeditorPritemplatemaster().getTId();
            sameNameValid(orgId, effectiveDept, templateName, tId);

            if (StringUtils.isEmpty(tId)) {
                // insert
                WdeditorPritemplatemaster wdeditorPritemplatemaster = templateVo.getWdeditorPritemplatemaster();
                wdeditorPritemplatemaster.setUpdateTime(new Date());
                wdeditorPritemplatemaster.setCreateTime(new Date());
                tId = idUtils.getNotExistsNextVal(OracleSequenceEnum.SEQ_ID_TEMPLATE_MASTER.getCode(), 1L).toString();
                wdeditorPritemplatemaster.setTId(tId);
                wdeditorPritemplatemasterMapper.insert(wdeditorPritemplatemaster);
            }
            List<WdeditorPritemplatedetail> details = templateVo.getDetails();
            if (CollectionUtils.isEmpty(details)) {
                return;
            }
            // 先删除
            wdeditorPritemplatedetailMapper.delete(new QueryWrapper<WdeditorPritemplatedetail>().eq(ServiceConstant.T_ID, tId));
            // 再新增
            String finalTId = tId;
            details.forEach(detail -> {
                detail.setTId(finalTId);
                String id = idUtils.getNotExistsNextVal(OracleSequenceEnum.SEQ_ID_TEMPLATE_DETAIL.getCode(), 1L).toString();
                detail.setId(id);
            });
            wdeditorPritemplatedetailService.saveBatch(details);
        }
    }

    private void sameNameValid(String orgId, String effectiveDept, String templateName, String tId) {
        QueryWrapper<WdeditorPritemplatemaster> queryWrapper = new QueryWrapper<WdeditorPritemplatemaster>().
                eq(ServiceConstant.ORG_ID, orgId)
                .eq(ServiceConstant.EFFECTIVE_DEPT, effectiveDept)
                .eq(ServiceConstant.TEMPLATE_NAME, templateName);
        if (StringUtils.isNotEmpty(tId)) {
            queryWrapper.ne(ServiceConstant.T_ID, tId);
        }
        WdeditorPritemplatemaster master = wdeditorPritemplatemasterMapper.selectOne(queryWrapper);
        if (master != null) {
            throw new CustomException("当前登录机构的有效范围:" + EffectiveEnum.getDescByType(effectiveDept).getDesc() + ",已存在模板:" + templateName + "");
        }
    }

    /**
     * Description: 个人模板列表
     * Param: [orgId]
     * return: java.util.List<com.wonders.hisdoctor.station.project.base.domain.WdeditorPritemplatemaster>
     * Author: tong-aj
     * Date: 2021/4/20
     */
    @Override
    public List<TemplateListVo> getTemplateList(String orgId, String effectiveDept, String templateName, String condition) {
        List<TemplateListVo> templateListVos = recordUseMapper.selectTemplateList(orgId, effectiveDept, templateName, condition);
        templateListVos.forEach(templateListVo -> templateListVo.setEffectiveName(Objects.requireNonNull(EffectiveEnum.getDescByType(templateListVo.getEffectiveDept())).getDesc()));
        return templateListVos;
    }

    @Override
    public void deleteTemplateList(List<String> tIds) {
        if (CollectionUtils.isEmpty(tIds)) {
            throw new CustomException("请选择需要删除的病历模板");
        }
        recordUseMapper.deleteTemplateList(tIds);
    }

    @Override
    public Map<String, List<Map<String, Object>>> getStaticDataList(String setId, String dId) {
        if(!setId.contains("NAME")){
            List<String> dIds = new ArrayList<>();
            dIds.add(dId);
            // 所有静态数据源
            List<WdeditorDssetStatic> allStatics = wdeditorDssetStaticMapper.selectList(new QueryWrapper<WdeditorDssetStatic>().in(ServiceConstant.SET_ID, setId));
            return dealWithStaticDataList(allStatics, dIds);
        } else {
            WdeditorDssetStatic wdeditorDssetStatic = new WdeditorDssetStatic();
            wdeditorDssetStatic.setSetId(setId);
            wdeditorDssetStatic.setDId(dId);
            wdeditorDssetStatic.setStaticShowField(setId);
            wdeditorDssetStatic.setStaticStorageField(setId.replace("NAME","CODE"));
            List<String> dIds = new ArrayList<>();
            dIds.add(dId);
            // 所有静态数据源
            List<WdeditorDssetStatic> allStatics = new ArrayList<>();
            allStatics.add(wdeditorDssetStatic);
            return dealWithStaticDataList(allStatics, dIds);
        }

    }

    @Override
    public List<StaticEditor> getStaticEditors(String modelId) {
        List<StaticEditor> staticEditors = recordUseMapper.getStaticEditors(modelId);
        getTmStaticEditors(staticEditors);
        return staticEditors;
    }

    /**
    *
    * Description: 手动处理中医诊断和证型
    * @author tongaijie
    * Param [staticEditors]
    * Return java.util.List<com.wonders.hisdoctor.station.project.record.vo.StaticEditor>
    * Date 2021/7/29
    */
    private List<StaticEditor> getTmStaticEditors(List<StaticEditor> staticEditors) {
        StaticEditor staticTmDiagEditor = new StaticEditor();
        StaticEditor staticTmTypeEditor = new StaticEditor();
        staticTmDiagEditor.setDId("5");
        staticTmDiagEditor.setReadField("TM_DIAG_CODE");
        staticTmDiagEditor.setSetId("TM_DIAG_NAME");

        staticTmTypeEditor.setDId("6");
        staticTmTypeEditor.setReadField("TM_TYPE_CODE");
        staticTmTypeEditor.setSetId("TM_TYPE_NAME");
        staticEditors.add(staticTmDiagEditor);
        staticEditors.add(staticTmTypeEditor);

        return staticEditors;
    }

    /**
     * Description: 将modelId对应的模板对象，设置其默认属性
     * Param: [modelId]
     * return: void
     * Author: tong-aj
     * Date: 2021/7/21
     */
    @Override
    public void setDefaultModel(String orgId, String modelId) {
        List<WdeditorDsset> allModels = wdeditorDssetMapper.selectList(new QueryWrapper<WdeditorDsset>().eq(ServiceConstant.ORG_ID, orgId));
        if (CollUtil.isNotEmpty(allModels)) {
            allModels.forEach(e -> e.setDefaultFlag(ServiceConstant.ZERO_STRING));
        }
        wdeditorDssetService.saveBatch(allModels);

        List<WdeditorDsset> models = wdeditorDssetMapper.selectList(new QueryWrapper<WdeditorDsset>().eq(ServiceConstant.MODEL_ID, modelId));
        if (CollUtil.isNotEmpty(models)) {
            models.forEach(e -> e.setDefaultFlag(ServiceConstant.ONE_STRING));
        }
        wdeditorDssetService.saveBatch(models);
    }

    /**
     * Description: 通过机构代码获取默认模板Id
     * Param: [orgId]
     * return: java.lang.String
     * Author: tong-aj
     * Date: 2021/7/21
     */
    @Override
    public String getDefaultModelId(String orgId) {
        List<WdeditorDsset> wdeditorDssets = wdeditorDssetMapper.selectList(new QueryWrapper<WdeditorDsset>().eq(ServiceConstant.ORG_ID, orgId).eq("DEFAULT_FLAG", ServiceConstant.ONE_STRING));
        if (CollUtil.isNotEmpty(wdeditorDssets)) {
            return wdeditorDssets.get(0).getModelId();
        }
        throw new CustomException("请管理员在“电子病历-模板维护”页面设置默认模板");
    }

    @Autowired
    public void setWdeditorDsMapper(WdeditorDsMapper wdeditorDsMapper) {
        this.wdeditorDsMapper = wdeditorDsMapper;
    }

    @Autowired
    public void setIdUtils(IdUtils idUtils) {
        this.idUtils = idUtils;
    }

    @Autowired
    public void setWdeditorDssetMapper(WdeditorDssetMapper wdeditorDssetMapper) {
        this.wdeditorDssetMapper = wdeditorDssetMapper;
    }

    @Autowired
    public void setWdeditorDssetStaticMapper(WdeditorDssetStaticMapper wdeditorDssetStaticMapper) {
        this.wdeditorDssetStaticMapper = wdeditorDssetStaticMapper;
    }

    @Autowired
    public void setWdeditorDssetLoadMapper(WdeditorDssetLoadMapper wdeditorDssetLoadMapper) {
        this.wdeditorDssetLoadMapper = wdeditorDssetLoadMapper;
    }

    @Autowired
    public void setWdeditorDssetStorgeMapper(WdeditorDssetStorgeMapper wdeditorDssetStorgeMapper) {
        this.wdeditorDssetStorgeMapper = wdeditorDssetStorgeMapper;
    }

    @Autowired
    public void setWdeditorDssetPropertyMapper(WdeditorDssetPropertyMapper wdeditorDssetPropertyMapper) {
        this.wdeditorDssetPropertyMapper = wdeditorDssetPropertyMapper;
    }

    @Autowired
    public void setRecordUseMapper(RecordUseMapper recordUseMapper) {
        this.recordUseMapper = recordUseMapper;
    }

    @Autowired
    public void setWdeditorDssetCustomService(IWdeditorDssetCustomService wdeditorDssetCustomService) {
        this.wdeditorDssetCustomService = wdeditorDssetCustomService;
    }

    @Autowired
    public void setApplicationContext(WebApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    @Autowired
    public void setWdeditorDssetCustomMapper(WdeditorDssetCustomMapper wdeditorDssetCustomMapper) {
        this.wdeditorDssetCustomMapper = wdeditorDssetCustomMapper;
    }

    @Autowired
    public void setWdeditorHistoryMapper(WdeditorHistoryMapper wdeditorHistoryMapper) {
        this.wdeditorHistoryMapper = wdeditorHistoryMapper;
    }

    @Autowired
    public void setWdeditorHistoryService(IWdeditorHistoryService wdeditorHistoryService) {
        this.wdeditorHistoryService = wdeditorHistoryService;
    }

    @Autowired
    public void setTokenService(TokenService tokenService) {
        this.tokenService = tokenService;
    }

    @Autowired
    public void setHospitalDictMapper(HospitalDictMapper hospitalDictMapper) {
        this.hospitalDictMapper = hospitalDictMapper;
    }

    @Autowired
    public void setRedisCache(RedisCacheService redisCache) {
        this.redisCache = redisCache;
    }

    @Autowired
    public void setWdeditorDssetService(IWdeditorDssetService wdeditorDssetService) {
        this.wdeditorDssetService = wdeditorDssetService;
    }

    @Autowired
    public void setWdeditorDssetLoadService(IWdeditorDssetLoadService wdeditorDssetLoadService) {
        this.wdeditorDssetLoadService = wdeditorDssetLoadService;
    }

    @Autowired
    public void setWdeditorDssetStaticService(IWdeditorDssetStaticService wdeditorDssetStaticService) {
        this.wdeditorDssetStaticService = wdeditorDssetStaticService;
    }

    @Autowired
    public void setWdeditorDssetStorgeService(IWdeditorDssetStorgeService wdeditorDssetStorgeService) {
        this.wdeditorDssetStorgeService = wdeditorDssetStorgeService;
    }

    @Autowired
    public void setWdeditorDssetPropertyService(IWdeditorDssetPropertyService wdeditorDssetPropertyService) {
        this.wdeditorDssetPropertyService = wdeditorDssetPropertyService;
    }

    @Autowired
    public void setWdeditorPritemplatemasterMapper(WdeditorPritemplatemasterMapper wdeditorPritemplatemasterMapper) {
        this.wdeditorPritemplatemasterMapper = wdeditorPritemplatemasterMapper;
    }

    @Autowired
    public void setWdeditorPritemplatedetailMapper(WdeditorPritemplatedetailMapper wdeditorPritemplatedetailMapper) {
        this.wdeditorPritemplatedetailMapper = wdeditorPritemplatedetailMapper;
    }

    @Autowired
    public void setWdeditorPritemplatedetailService(IWdeditorPritemplatedetailService wdeditorPritemplatedetailService) {
        this.wdeditorPritemplatedetailService = wdeditorPritemplatedetailService;
    }

    @Autowired
    public void setPatMasterIndexMapper(PatMasterIndexMapper patMasterIndexMapper) {
        this.patMasterIndexMapper = patMasterIndexMapper;
    }

    @Autowired
    public void setCommonUtil(CommonUtil commonUtil) {
        this.commonUtil = commonUtil;
    }
}
